import { ComponentClass } from 'react'
import Taro, { Component, Config } from '@tarojs/taro'
import { View, Text, Image, Input } from '@tarojs/components'
import ImageButton from '../../components/img-button'
import { connect } from '@tarojs/redux'

import logoImg from '../../asset/images/logo.png'
import buttonImg from '../../asset/images/apply_button@2x.png'

import { Utils } from '../../utils/utils'
import { User as UserUtils } from '../../utils/user'
import LoginService from '../../services/login'
const mobileValidateErrorTips = '您输入的电话号码有误，请重新输入'
const mobileNullErrorTips = '请输入电话号码'
const codeNullErrorTips = '请输入验证码'

import './index.scss'

// #region 书写注意
// 
// 目前 typescript 版本还无法在装饰器模式下将 Props 注入到 Taro.Component 中的 props 属性
// 需要显示声明 connect 的参数类型并通过 interface 的方式指定 Taro.Component 子类的 props
// 这样才能完成类型检查和 IDE 的自动提示
// 使用函数模式则无此限制
// ref: https://github.com/DefinitelyTyped/DefinitelyTyped/issues/20796
//
// #endregion

const utils = new Utils()
const userUtils = new UserUtils()
const loginService = new LoginService()

type PageStateProps = {
  codeTimerCount: number,   // 短信验证码发送时间间隔
  curTimerCount: number,    // 短信验证码发送后的重发倒数秒数
  codeTimer: any,           // 短信验证码发送定时器
  effects: any,             // 可以获取action的loading状态
}

type PageDispatchProps = {
  login: (mobile: string, code: string, callback: Function) => void,
  updateCurTimerCount: (count: number) => void,
  updateCodeTimer: (codeTimer: any) => void,
}

type PageOwnProps = {}

type PageState = {
  // 用户手机号
  mobile: string,
  // 短信验证码
  code: string,
  // 手机号输入错误提示信息
  mobileErrorMsg: string,
  // 验证码输入错误提示信息
  codeErrorMsg: string,
  // 登录后跳转到的页面url
  redirectTo: string,
  // 当前聚焦的组件名
  elementFocus: string,
}

type IProps = PageStateProps & PageDispatchProps & PageOwnProps

interface LoginPage {
  props: IProps;
  state: PageState;
}

@connect(({ login, common, loading }) => ({
  ...login,
  ...common,
  ...loading,
}), (dispatch) => ({
  login(mobile: string, code: string, callback: Function) {
    dispatch({
      type: 'login/login',
      payload: {
        mobile,
        code,
        callback,
      }
    })
  },
  updateCurTimerCount(count: number) {
    dispatch({
      type: 'login/save',
      payload: {
        curTimerCount: count,
      }
    })
  },
  updateCodeTimer(codeTimer: number) {
    dispatch({
      type: 'login/save',
      payload: {
        codeTimer,
      }
    })
  }
}))
class LoginPage extends Component {

  constructor(props) {
    super(props);

    // // 测试代码
    // this.setState({
    //   mobile: '13012345678',
    //   code: '123456'
    // })
  }

  componentWillReceiveProps(nextProps) { 

    // 检查登录action的loading状态
    const nextLoginLoading = nextProps.effects['login/login']
    if (nextLoginLoading) {
      this._showLoadingCenter()
    } else {
      this._hideLoadingCenter()
    }
  }

  componentWillMount() {    
    // 获取url中的redirectTo参数
    const { redirectTo } = this.$router.params
    this.setState({
      redirectTo: redirectTo ? decodeURIComponent(redirectTo) : ''
    })
  }

  componentDidMount() { 
    // 自动填写手机号
    this.fillMobileWithCache()
  }

  componentWillUnmount() {
    this._clearTimer()
  }

  componentDidShow() { }

  componentDidHide() { 
    this._clearTimer()
  }

  render() {
    const { curTimerCount } = this.props

    return (
      <View className='login-page-container'>
        {/* logo  */}
        <View className="logo-box">
          <Image className="logo" src={logoImg}></Image>
        </View>
        {/* <!-- 描述信息 --> */}
        <View className="description-box">
          <Text className="big-desc">手机号码登录</Text>
          <Text className="detail-desc">输入手机号码以及验证码，即可登录</Text>
        </View>
        {/* <!-- 输入信息分块 --> */}
        <View className="input-box">
          <View className={`input-container ${this.state.elementFocus === 'phone' ? 'focus' : ''}`}>
            <Input value={this.state.mobile} type="number" placeholderClass="placeholder" placeholder="输入手机号码" className='input'
              data-focus="phone"
              onFocus={this.onFocus.bind(this)}
              onBlur={this.onBlur.bind(this)} 
              onInput={this.onMobileInput.bind(this)}/>
            {this.state.mobile ? (<Text className="iconfont icon-guanbi1 icon-delete" onClick={this.onDelete.bind(this)}></Text>) : null}
          </View>

          {this.state.mobileErrorMsg ? (
            <View className="error">
              <Text className="iconfont icon-icon error-icon"></Text>
              <Text>{this.state.mobileErrorMsg}</Text>
            </View>) : ''}

          <View className={`input-container ${this.state.elementFocus === 'code' ? 'focus' : ''}`}>
            <Input value={this.state.code} type="number" placeholderClass='placeholder' placeholder='输入验证码' className='input' style="width: 60%;"
              data-focus="code"
              onFocus={this.onFocus.bind(this)}
              onBlur={this.onBlur.bind(this)} 
              onInput={ this.onCodeInput.bind(this) }/>
            <View className="get-code">
              <Text className="" onClick={this.onGetCode.bind(this)}>{curTimerCount > 0 ? curTimerCount + '秒后重发' : '获取验证码'}</Text>
            </View>
          </View>

          {this.state.codeErrorMsg ?
            (<View className="error">
              <Text className="iconfont icon-icon error-icon"></Text>
              <Text>{this.state.codeErrorMsg}</Text>
            </View>) : null}

        </View>

        {/* <!-- 按钮分块 --> */}
        <View className="button-box" onClick={this.onLogin.bind(this)}>
          <ImageButton imgSrc={buttonImg} buttonText={'登录'} />
        </View>
      </View>
    )
  }

  /**
   * 删除按钮监听方法
   * @param {*} e 
   */
  onDelete(e) {
    this.setState({
      mobile: '',
    })
  }

  /**
   * 监听输入框聚焦
   * @param {*} e 
   */
  onFocus(e) {
    const {
      focus
    } = e.currentTarget.dataset

    // 设置聚焦组件名
    this.setState({
      elementFocus: focus,
    })
  }

  /**
   * 验证码输入监听方法
   * @param e 
   */
  onMobileInput(e) {
    this.setState({
      mobile: e.target.value,
    })
  }

  /**
   * 验证码输入监听方法
   * @param e 
   */
  onCodeInput(e) {
    this.setState({
      code: e.target.value,
    })
  }

  /**
   * 监听输入框失去焦点
   * @param {*} e 
   */
  onBlur(e) {
    const {
      focus
    } = e.target.dataset

    if ('phone' === focus) {
      const mobile = e.detail.value
      let mobileErrorMsg = ''
      if (!mobile) {
        mobileErrorMsg = mobileNullErrorTips
      } else {
        const isValidate = utils.phoneNumberValidation(mobile)
        if (!isValidate) {
          mobileErrorMsg = mobileValidateErrorTips
        }
      }
      this.setState({
        // mobile,
        mobileErrorMsg: mobileErrorMsg,
      })
    }

    this.setState({
      elementFocus: '',
    })
  }

  /**
   * 获取短信验证码方法 
   * @param {*} e 
   */
  onGetCode(e) {

    // 正在倒数的情况下，不继续
    if (this.props.curTimerCount > 0) {
      return
    }

    // 验证手机号是否正确
    let mobileErrorMsg = ''
    const isValidate = utils.phoneNumberValidation(this.state.mobile)
    if (!this.state.mobile) {
      mobileErrorMsg = mobileNullErrorTips
    } else {
      if (!isValidate) {
        mobileErrorMsg = mobileValidateErrorTips
      }
    }
    this.setState({
      mobileErrorMsg
    })

    if (!isValidate) {
      return
    }

    this._showLoadingCenter('加载中')

    // setTimeout(() => {
    //   const res = {
    //     code: 0
    //   }
    //   // 请求验证码
    //   let timmerId
    //   let curTimerCount = 0

    //   this._hideLoadingCenter()

    //   const code = res['code']
    //   if (code === 0) {
    //     Taro.showToast({
    //       title: '验证码已发送',
    //       icon: 'none',
    //       duration: 3000
    //     })
    //   }

    //   if (code === 0 && isValidate) {
    //     curTimerCount = this.props.codeTimerCount
    //     // 启动定时器
    //     // 每秒减1
    //     timmerId = setInterval(() => {

    //       const curTimerCount = this.props.curTimerCount
    //       let counter = curTimerCount - 1

    //       // console.log('计时中, counter = ', counter)

    //       if (counter <= 0) {
    //         // 清除定时器
    //         if (this.props.codeTimer) {
    //           clearInterval(this.props.codeTimer);
    //           this.props.updateCodeTimer(null)
    //           // console.log('计时结束, codeTimer = ', this.props.codeTimer)
    //         }
    //         // 倒数清零
    //         counter = 0
    //       }

    //       this.props.updateCurTimerCount(counter)

    //     }, 1000)

    //     this.props.updateCodeTimer(timmerId)
    //     this.props.updateCurTimerCount(curTimerCount)
    //   }


    //   this.props.updateCurTimerCount(curTimerCount)
    // }, 2000)

    loginService.getSmsCode(this.state.mobile).then(res => {

      // 请求验证码
      let timmerId
      let curTimerCount = 0

      this._hideLoadingCenter()

      const code = res['code']
      if (code === 0) {
        Taro.showToast({
          title: '验证码已发送',
          icon: 'none',
          duration: 3000
        })
      }

      if (code === 0 && isValidate) {
        curTimerCount = this.props.codeTimerCount
        // 启动定时器
        // 每秒减1
        timmerId = setInterval(() => {

          const curTimerCount = this.props.curTimerCount
          let counter = curTimerCount - 1

          // console.log('计时中, counter = ', counter)

          if (counter <= 0) {
            // 清除定时器
            if (this.props.codeTimer) {
              clearInterval(this.props.codeTimer);
              this.props.updateCodeTimer(null)
              // console.log('计时结束, codeTimer = ', this.props.codeTimer)
            }
            // 倒数清零
            counter = 0
          }
          this.props.updateCurTimerCount(counter)
        }, 1000)

        this.props.updateCodeTimer(timmerId)
        this.props.updateCurTimerCount(curTimerCount)
      }

      this.props.updateCurTimerCount(curTimerCount)
    })
  }

  /**
   * 登录按钮处理方法
   * @param {*} e 
   */
  onLogin(e) {
    // console.log('onLogin, mobile = ', this.state.mobile)

    // 验证手机号是否正确
    const isValidate = utils.phoneNumberValidation(this.state.mobile)
    let mobileErrorMsg = ''
    if (!this.state.mobile) {
      mobileErrorMsg = mobileNullErrorTips
    } else {
      if (!isValidate) {
        mobileErrorMsg = mobileValidateErrorTips
      }
    }

    let codeErrorMsg = ''
    if (!this.state.code) {
      codeErrorMsg = codeNullErrorTips
    }

    this.setState({
      mobileErrorMsg,
      codeErrorMsg,
    })

    // 手机或验证码有误，不继续
    if (mobileErrorMsg || codeErrorMsg) {
      return
    }

    this.props.login(this.state.mobile, this.state.code, () => {
      // console.log('login callback!! this.state.redirectTo = ', this.state.redirectTo)
      // 隐藏加载框, 必须！！
      this._hideLoadingCenter()

      setTimeout(() => {
        Taro.showToast({
          title: '登录成功',
          icon: 'none',
          duration: 2000,
        })
      }, 0)

      // 有redirectTo则跳转，否则跳转到首页
      if (this.state.redirectTo) {

        if (process.env.TARO_ENV === 'weapp') {
          if (utils.isTabUrl(this.state.redirectTo)) {
            Taro.switchTab({
              url: this.state.redirectTo
            })
          } else {
            Taro.navigateTo({
              url: this.state.redirectTo
            })
          }
        } else {
          Taro.navigateTo({
            url: this.state.redirectTo
          })
        }

      } else {
        let url = '/pages/home/index'

        if (process.env.TARO_ENV === 'weapp') {
          // 跳转到页面
          Taro.switchTab({
            url
          })
        } else {
          Taro.navigateTo({
            url
          })
        }
      }
    })
  }

  /**
   * 读取缓存中的手机号码，自动填写手机号
   */
  fillMobileWithCache() {
    // 读取缓存中的用户信息，自动填写手机号
    const userInfo = userUtils.getUserFromLocalStorage()
    if (userInfo) {
      const { mobile } = userInfo
      if (mobile) {
        this.setState({
          mobile,
        })
      }
    }
  }

  /**
   * 清除定时器
   */
  _clearTimer() {
    const { codeTimer } = this.props
    console.log('_clearTimer, codeTimer = ', codeTimer)
    // 清除定时器
    if (codeTimer) {
      clearInterval(codeTimer)
      this.props.updateCodeTimer(null)
      this.props.updateCurTimerCount(0)
    }
  }

  _showLoadingCenter(title?) {
    // 使用小程序的loading效果
    Taro.showLoading({
      title: title || '登录中',
      mask: true,
    })
  }

  _hideLoadingCenter() {
    Taro.hideLoading()
  }

}

// #region 导出注意
//
// 经过上面的声明后需要将导出的 Taro.Component 子类修改为子类本身的 props 属性
// 这样在使用这个子类时 Ts 才不会提示缺少 JSX 类型参数错误
//
// #endregion

export default LoginPage as ComponentClass<PageOwnProps, PageState>
